#include "ContextEGL1.h"

#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#include <TCHAR.h>
#else
// for linux and canmore
#endif

static bool TestEGLError(char* pszLocation)
{
  /*
  eglGetError returns the last error that has happened using egl,
  not the status of the last called function. The user has to
  check after every single egl call or at least once every frame.
  */
  EGLint iErr = eglGetError();
  if (iErr != EGL_SUCCESS)
  {
    printf("%s failed (%d).\n", pszLocation, iErr);
    return false;
  }

  return true;
}

bool ContextEGL1::init(WindowInterface* window)
{
  hWnd = window->handle();
  eglWindow = (NativeWindowType)hWnd;

#ifdef _WIN32
  hDC = GetDC(hWnd);
  if (!hDC)
  {
    MessageBox(0, _T("Failed to create the device context"), _T("Error"), MB_OK|MB_ICONEXCLAMATION);
    return false;
  }
  eglDisplay = eglGetDisplay((NativeDisplayType)hDC);
  if(eglDisplay == EGL_NO_DISPLAY)
    eglDisplay = eglGetDisplay((NativeDisplayType) EGL_DEFAULT_DISPLAY);
#else
  eglDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY);
#endif
  if(eglDisplay == EGL_NO_DISPLAY)
  {
    TestEGLError("eglGetDisplay returned EGL_NO_DISPLAY\n");
    return false;
  }

  EGLint iMajorVersion, iMinorVersion;
  if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion))
  {
    TestEGLError("eglInitialize() failed");
    return false;
  }

/*  // need link to libEGL.so
      ok = eglBindAPI(EGL_OPENGL_ES_API);
      if (!ok) {
          printf("eglBindAPI failed!\n");
          return false;
      }
*/

  int i = 0;
  pi32ConfigAttribs[i++] = EGL_RED_SIZE;
  pi32ConfigAttribs[i++] = 8;
  pi32ConfigAttribs[i++] = EGL_GREEN_SIZE;
  pi32ConfigAttribs[i++] = 8;
  pi32ConfigAttribs[i++] = EGL_BLUE_SIZE;
  pi32ConfigAttribs[i++] = 8;
  pi32ConfigAttribs[i++] = EGL_ALPHA_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_ALPHA) ? 8 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_DEPTH_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_DEPTH) ? 16 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_STENCIL_SIZE;
  pi32ConfigAttribs[i++] = (flag&CF_STENCIL) ? 8 : EGL_DONT_CARE;
  pi32ConfigAttribs[i++] = EGL_SAMPLE_BUFFERS;
  pi32ConfigAttribs[i++] = (flag&CF_MULTISAMPLE) ? 1 : 0;
  pi32ConfigAttribs[i++] = EGL_SURFACE_TYPE;
  pi32ConfigAttribs[i++] = EGL_WINDOW_BIT;
  pi32ConfigAttribs[i++] = EGL_NONE;

  /*
  Step 4 - Find a config that matches all requirements.
  eglChooseConfig provides a list of all available configurations
  that meet or exceed the requirements given as the second
  argument. In most cases we just want the first config that meets
  all criteria, so we can limit the number of configs returned to 1.
  */
  int iConfigs;
  if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1))
  {
    TestEGLError("eglChooseConfig() failed");
    return false;
  }

  eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, eglWindow, NULL);

  if(eglSurface == EGL_NO_SURFACE)
  {
    eglGetError(); // Clear error
    eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, NULL, NULL);
  }

  if (!TestEGLError("eglCreateWindowSurface"))
  {
    return false;
  }

  eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
  if (!TestEGLError("eglCreateContext"))
  {
    return false;
  }

  eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
  if (!TestEGLError("eglMakeCurrent"))
  {
    return false;
  }

  return true;
}


void ContextEGL1::shutdown()
{
  eglDestroyContext(eglDisplay, eglContext);
  eglDestroySurface(eglDisplay, eglSurface);

  eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  eglTerminate(eglDisplay);

#ifdef _WIN32
  // Release the device context
  if (hDC) ReleaseDC(hWnd, hDC);
#endif
}

void ContextEGL1::update()
{
  eglSwapBuffers(eglDisplay, eglSurface);
}
